/*! SmartTable 1.0.0
 */

(function ($){

    const _calColWidth = function (table ,options){
        //如果列是px，则表格认为是px，如果是%，则将所有列的%相加，供后面计算解决超过100%的问题，
        let sumWidth = 0 , colUnit = options.columns[0].width.endsWith("%") ? "%":"px";

        for(let i=0;i< options.columns.length; i++) {
            let column = options.columns[i];
            if(column.width.endsWith("%") && colUnit === "%"){
                sumWidth = sumWidth + parseFloat(column.width.replace("%",""));
            }else if(column.width.endsWith("px") && colUnit === "px"){
                sumWidth = sumWidth + parseFloat(column.width.replace("px",""))
            }else{
                alert("列宽度单位必须一致。");
                return ;
            }
        }

        for(let i=0;i< options.columns.length; i++) {
            let column = options.columns[i];
            column.realWidth = colUnit === "%" ?
                Math.floor(parseFloat(column.width.replace("%","")) / sumWidth * 10000) /100  + "%" : column.width ;//按列实际像素走
            //如果table宽度单位是%，列宽度是%，则换算列宽度%，解决百分比大于100的问题，grid可解决但影响行合并,
        }

        options.colUnit = colUnit;
        options.sumWidth = sumWidth;
    }

    const _goToPage = function (table , pageNum){
        let options = $(table).data("options");
        let pageLength = options.pageLength ;
        $(".st-fnumpage",table).val(pageNum);

        let startRowIndex , endRowIndex ;
        let trs = $(".st-tr",table);

        if(options.pageMode == "server"){
            options.turnPage(pageNum , pageLength);
        }else{
            let rowCount = $(".st-tr",table).length;
            startRowIndex = pageLength * (pageNum-1);
            endRowIndex = pageLength * pageNum < rowCount ?  pageLength * pageNum : rowCount;

            let curShowTrs = $(".st-tr:visible",table);
            //翻页去掉之前的选中
            let checkbox = $(".st-checkbox",table).prop("checked",false);
            for(let i=0; i < checkbox.length; i++){
                let colIndex = checkbox.eq(i).parents('th').index();
                curShowTrs.each(function(){ //将显示的tr中的选择框去掉选中。
                    $('td:eq('+colIndex+') :checkbox' , this).prop("checked",false);
                });
            }
            //隐藏之前显示的行
            curShowTrs.hide();

            for(let i=startRowIndex;i<endRowIndex;i++){
                trs.eq(i).show();
            }

            $(".st-startrow",table).text(startRowIndex+1);
            $(".st-endrow",table).text(endRowIndex);

        }
    }

    const _goToFirstPage = function (){
        _goToPage($(this).parents(".st-table") , 1);
    }

    const _goToPrevPage = function (){
        let table = $(this).parents(".st-table");
        let pageNum = parseInt($(".st-fnumpage",table).val());
        if(pageNum > 1){
            _goToPage(table , pageNum -1);
        }
    }

    const _goToNextPage = function (){
        let table = $(this).parents(".st-table");
        let pageNum = parseInt($(".st-fnumpage",table).val());
        let totalPageNum = parseInt($(".st-totalpage",table).text());
        if(pageNum < totalPageNum){
            _goToPage(table , pageNum + 1);
        }
    }

    const _goToLastPage = function (){
        let table = $(this).parents(".st-table");
        let pageNum = parseInt($(".st-totalpage",table).text());
        _goToPage(table , pageNum);
    }

    const _goToInputPage = function (){
        let table = $(this).parents(".st-table");
        let inputValue = $(this).val();
        let pageNum;
        if(!(/(^[0-9]\d*$)/.test(inputValue))){
            pageNum = 1; //非数值跳转到首页
        }else{
            pageNum = parseInt(inputValue);
            if(pageNum < 1){
                pageNum = 1;
            }else{
                let totalPageNum = parseInt($(".st-totalpage",table).text());
                pageNum = pageNum > totalPageNum ? totalPageNum : pageNum;
            }
        }
        _goToPage(table , pageNum);
    }


    const _setPageLength = function (){
        let selectObj = this;
        var pageLength = parseInt($(selectObj).val());
        var table = $(selectObj).parents(".st-table");
        var rowCount = $(".st-tr",table).length;

        var options = table.data("options");
        options.pageLength = pageLength;

        var pageNum = parseInt($(".st-fnumpage",table).val());

        var totalPage;
        if(options.pageMode == "server"){
            var totalCount = parseInt($(".st-totalrow",table).text());
            totalPage = Math.floor((totalCount + pageLength - 1) / pageLength); //总页数
        }else{
            totalPage = Math.floor((rowCount + pageLength - 1) / pageLength); //总页数
            $(".st-totalpage",table).text(totalPage);
        }

        if(pageNum > totalPage){
            pageNum = totalPage;
        }

        _goToPage(table , pageNum);
    }

    //分组
    const _group = function (table , level , groupFieldArr , data, startIndex ){

        var gcol = groupFieldArr[level];
        var groupInfoArr = [] ;
        for(let i = 0 ; i< data.length;i++){
            if(i==0){
                var group = {}
                group.gname = data[0][gcol];
                group.minIndex = 0;
                groupInfoArr.push(group);
            }else{
                if( data[i][gcol] != group.gname){
                    groupInfoArr[groupInfoArr.length-1].maxIndex = i-1;
                    var group = {}
                    group.gname = data[i][gcol];
                    group.minIndex = i;
                    groupInfoArr.push(group);
                }
                if(i== data.length -1){
                    groupInfoArr[groupInfoArr.length-1].maxIndex = i;
                }
            }
        }

        var tdsArr = [];
        var columns = $(table).data("options").columns;
        for(let i=0;i<columns.length;i++ ){
            if(columns[i].data == groupFieldArr[level]){
                tdsArr.push($("tbody>tr",table).find('td:eq('+i+')'));
            }
        }

        for(let i = 0 ; i< groupInfoArr.length;i++){
            let nextLevelData = [] ;
            if(groupInfoArr[i].maxIndex > groupInfoArr[i].minIndex ){
                for(var j=groupInfoArr[i].minIndex; j <= groupInfoArr[i].maxIndex; j++){
                    if(j == groupInfoArr[i].minIndex){
                        //算回在原数组中的索引
                        for(var m=0;m<tdsArr.length;m++){
                            tdsArr[m].eq(j+startIndex).attr("rowspan",groupInfoArr[i].maxIndex - groupInfoArr[i].minIndex + 1);
                        }
                    }else{
                        for(var m=0;m<tdsArr.length;m++){
                            tdsArr[m].eq(j+startIndex).hide();
                        }
                    }
                    if(level < groupFieldArr.length-1) nextLevelData.push(data[j]);
                }
                if(level < groupFieldArr.length-1) _group(table,level +1, groupFieldArr ,  nextLevelData , groupInfoArr[i].minIndex + startIndex);
            }
        }
    }


    const _sort = function (){
        let thJqo = $(this);
        let colIndex = thJqo.index(),table = thJqo.parents(".st-table"),trs = $(".st-tr",table);
        let sortArr = [];

        let order = thJqo.attr("order") == "asc" || thJqo.attr("order") == undefined? "desc" : "asc";
        thJqo.attr("order",order);

        $(".st-sort-icon",table).remove();
        if(order == "desc"){
            thJqo.find(".th-span").append('<span class="st-sort-icon">▼</span>');
        }else{
            thJqo.find(".th-span").append('<span class="st-sort-icon">▲</span>');
        }

        var sortType = "string";
        var sortEle = "";
        if(thJqo.attr("sort") != undefined && thJqo.attr("sort") != ""){
            let sortAttr = thJqo.attr("sort").split("|");
            sortType = sortAttr[0];
            sortEle = sortAttr.length === 2 ? sortEle = sortAttr[1] : "";
        }

        for(let i=0;i<trs.length;i++){
            let td = trs.eq(i).find("td:eq("+colIndex+")");
            let value = "";
            if(sortEle == ""){
                if(td.children().length == 0){
                    value = td.html().trim();
                }else{ //否则查找第一个显示输入框的value
                    let input = $("input:visible",td);
                    value = input.length > 0 ?input.eq(0).val() : td.html().trim();
                }
            }else{
                let ele = $(sortEle,td);//指定排序的元素"[name='test']"、".test-class"
                try{
                    let tagName = ele.get(0).tagName.toLowerCase();
                    value = tagName == "input" || tagName == "select" || tagName == "textarea" ? ele.val() : ele.html().trim();
                }catch (e) {
                    value = td.html().trim();
                    console.log("排序类型错误1");
                }
            }
            if(sortType == "number"){
                try{
                    let v = parseFloat(value);
                    if(!isNaN(v)) value = v;
                }catch (e) {
                    console.log("排序类型错误2");
                }
            }

            if(i === 0){
                sortArr.push({ value:value, tr: trs.eq(0) } );
            }else{
                let flag = false;
                for (let j = 0; j < sortArr.length; j++) {
                    if (order == "desc") {
                        //空字符串放到最后，js中 "" 等于0，所以要判断类型，否则0也放到了最后
                        if(sortType=="number" && typeof(value) == "string" && value == ""){
                            sortArr.push({value: value, tr: trs.eq(i)});
                            flag = true;
                            break;
                        }else if(value >= sortArr[j].value){
                            sortArr.splice(j, 0, {value: value, tr: trs.eq(i)});
                            flag = true;
                            break;
                        }
                    }else if(order == "asc"){
                        //空字符串放到最上面
                        if(sortType=="number" && typeof(value) == "string" && value == ""){
                            sortArr.splice(0, 0, {value: value, tr: trs.eq(i)});
                            flag = true;
                            break;
                        }else if(value < sortArr[j].value){
                            sortArr.splice(j, 0, {value: value, tr: trs.eq(i)});
                            flag = true;
                            break;
                        }
                    }else{

                    }
                }
                if (flag == false) { //最小添加到最后
                    sortArr.push({value: value, tr: trs.eq(i)});
                }
            }
        }

        for (let i = 0; i < sortArr.length; i++) {
            if(i===0){
                sortArr[i].tr.insertBefore(trs.eq(0));
            }else{
                sortArr[i].tr.insertAfter(sortArr[i-1].tr);
            }
        }
    }


    //设置分页信息
    const  _initPaginate =  function ( table , totalCount , pageNum){

        var options = $(table).data("options");

        if(options.paging == true){
            var pageLength = options.pageLength;
            var pageMode = options.pageMode;

            var rowCount = $(".st-tr",table).length;

            if(rowCount > 0){

                $(".st-fnorow",table).hide();
                $(".st-fpage",table).show();

                var totalPage;
                if(pageMode == "server"){ //后端分页

                    $(".st-startrow",table).text(pageLength * (pageNum -1) + 1 );
                    $(".st-endrow",table).text(pageNum * pageLength > totalCount ? totalCount : pageNum * pageLength );
                    $(".st-totalrow",table).text(totalCount);
                    $(".st-fnumpage",table).val(pageNum);

                    totalPage = Math.floor((totalCount + pageLength - 1) / pageLength);
                    $(".st-totalpage",table).text(totalPage);

                }else{
                    $(".st-totalrow",table).text(rowCount);
                    totalPage = Math.floor((rowCount + pageLength - 1) / pageLength);
                    $(".st-totalpage",table).text(totalPage);  //总页数
                    _goToPage(table ,1);
                }

                //添加自定义每页显示条数
                var flag = false;
                $(".st-fsetpagecount option",table).each(function(){
                    if(pageLength == $(this).val()){
                        flag = true;
                        return flag;
                    }
                });
                if(flag == false){
                    $('<option value='+pageLength+ '>'+pageLength+'</option>').appendTo( $(".st-fsetpagecount",table));

                }
                $(".st-fsetpagecount",table).val(pageLength);

            }else{
                $(".st-fpage",table).hide();
                $(".st-fnorow",table).show();
            }

        }else{

        }
    }

    $.fn.extend({

        smartTable:function(options){

            let thead , tr ,th , column , tbody , thSpan , tfoot , tftr , tftd;

            let tableJqo =  $(this);

            if(!tableJqo.hasClass("st-table")){
                tableJqo.attr("oclass",tableJqo.attr("class")==undefined? "" : tableJqo.attr("class"))
                    .attr("ostyle",tableJqo.attr("style")==undefined? "" : tableJqo.attr("style"));
                $(this).addClass("st-table");
            }
            tableJqo.removeClass("st-border").removeClass("st-zebra").html("");

            if(options.border == undefined) options.border = true;//表格本身不带边框，但初始化没有设置则默认有边框
            if(options.border == true) tableJqo.addClass("st-border");

            //隔行换色
            if(options.zebra == undefined)  options.zebra = true;
            if(options.zebra == true) $(this).addClass("st-zebra");

            if(options.paging == undefined) options.paging = true;
            if(options.pageLength == undefined) options.pageLength = 10;
            if(options.pageMode == undefined) options.pageMode = "local";


            tableJqo.data("options",options);

            thead = $('<thead/>').appendTo( this ).addClass("st-head");
            tr = $("<tr/>").appendTo( thead ).addClass("st-htr");

            _calColWidth(this , options);

            if(options.fixedLeft != undefined || options.fixedRight != undefined){
                if( options.colUnit == "%" ){
                    alert("如要固定列，列宽度必须是px");
                    return ;
                }
                if(tableJqo.parent(".st-wrap-div").length != 1){
                    tableJqo.css("width",options.sumWidth);
                    let fdBorder = "";
                    if(options.border == true){
                        tableJqo.css("border","none");
                        fdBorder = "st-fd-border";
                    }
                    let str = `<div class="st-wrap-div ${tableJqo.attr("oclass")} ${fdBorder}" style="${tableJqo.attr("ostyle")};overflow-x: auto;">`;
                    tableJqo.wrap(str);
                }
            }
            let fixedLeft = 0;

            for(let i=0;i< options.columns.length; i++){
                column = options.columns[i];
                th = $("<th/>").addClass("st-th").css({"width":column.realWidth});

                if(column.thStyle != undefined) th.attr("style",column.thStyle);
                column.thAlign != undefined ? th.addClass("text-"+ column.thAlign) : th.addClass("text-center"); //text-left text-right text-center

                if(options.fixedLeft != undefined && i < options.fixedLeft ){
                    column.left = fixedLeft; //后面td要用到column.left
                    th.addClass("st-fixed-left").css({"left": column.left + "px"});
                    if(options.fixedLeft == i+1) th.addClass("st-fixed-left-last");
                    fixedLeft = fixedLeft + parseFloat(column.realWidth.replace("px",""));
                }
                if(options.fixedRight != undefined && i >= options.columns.length - options.fixedRight ){
                    let fixedRight = 0;
                    for(let j=options.columns.length-1 ; j > i; j--){
                        fixedRight = fixedRight + parseFloat(options.columns[j].realWidth.replace("px",""));
                    }
                    column.right = fixedRight;
                    th.addClass("st-fixed-right").css({"right": column.right + "px"});
                    if(options.fixedRight == options.columns.length - i) th.addClass("st-fixed-right-first");
                }

                if(options.sort == true && column.sort != false){
                    th.css({"cursor":"pointer"}).bind('click', _sort);
                    if(column.sort != undefined) th.attr("sort",column.sort);
                }

                thSpan = $("<span class='th-span'></span>").appendTo( th ).html(column.title);
                if(thSpan.children().length > 0) thSpan.css({"padding":"0px"});
                th.appendTo( tr );
            }

            tbody = $('<tbody/>').appendTo( this ).addClass("st-body");

            if(options.height != undefined){
                let stWrapDivJqo = tableJqo.parent(".st-wrap-div");
                thead.css({"position":"sticky","top":0,"z-index":3});
                if(stWrapDivJqo.length != 1){
                    let fdBorder = "";
                    if(options.border == true){
                        tableJqo.css("border","none");
                        fdBorder = "st-fd-border";
                    }
                    let str = `<div class="st-wrap-div ${tableJqo.attr("oclass")} ${fdBorder}" 
                            style="${tableJqo.attr("ostyle")};height:${options.height};overflow-y: auto;">`;
                    tableJqo.wrap(str);
                    tableJqo.css({"width":"100%"});
                }else{
                    stWrapDivJqo.css({"height":options.height,"overflow-y": "auto"});
                }
            }

            if(options.paging == true){

                tfoot = $('<tfoot class="st-foot"></tfoot>').appendTo( this );
                tftr = $('<tr></tr>').appendTo( tfoot );
                tftd = $('<td colspan="' + options.columns.length +'"></td>').appendTo( tftr );

                let fNoRow = `<div class="st-fnorow">表中数据为空</div>`;
                let stickyLeft = "";
                let stickyRight = "";
                if(options.fixedLeft != undefined || options.fixedRight != undefined){
                    stickyLeft = ";position: sticky;left: 0";
                    stickyRight = ";position: sticky;right: 0";
                    fNoRow = `<div class="st-fnorow" style="text-align: left"><div style="position: sticky;left: calc(50% - 100px);width: 200px;display: inline-block;text-align: center;">表中数据为空</div></div>`;
                }
                $(fNoRow).appendTo( tftd );

                $(`<div class="st-fpage">
                        <div style="display: flex;justify-content: space-between;">
                            <div class="st-fpage-left" style="${stickyLeft}">
                                显示第 <span class="st-startrow">0</span> 至 <span class="st-endrow">0</span> 项结果，共 <span class="st-totalrow">0</span> 项
                            </div>
                            <div class="st-fpage-right" style="${stickyRight}">
                               <button class="st-fbtnpage st-goToFirstPage">首页</button>
                               <button class="st-fbtnpage st-goToPrevPage">上一页</button>
                               <input class="st-fnumpage" onkeyup="value=value.replace(/[^\\d]/g,\'\')"> <span class="st-fnumpage-separator">/</span> <span class="st-totalpage"></span>
                               <button class="st-fbtnpage st-goToNextPage">下一页</button>
                               <button class="st-fbtnpage st-goToLastPage">尾页</button>
                               <span class="st-fpage-mr">|</span><span class="st-fpage-mr">每页</span>
                                   <select class="st-fsetpagecount"><option value=5>5</option><option value=10>10</option><option value=20>20</option><option value=50>50</option></select><span>条</span>
                            </div>
                        </div>
                        </div>`).appendTo( tftd );

                $(".st-goToFirstPage",this).bind('click', _goToFirstPage);
                $(".st-goToPrevPage",this).bind('click', _goToPrevPage);
                $(".st-goToNextPage",this).bind('click', _goToNextPage);
                $(".st-goToLastPage",this).bind('click', _goToLastPage)
                $(".st-fnumpage",this).bind('blur', _goToInputPage);
                $(".st-fsetpagecount",this).bind('change', _setPageLength);

            }

            //全选触发事件
            $(".st-checkbox",this).bind('click', function(){
                let obj = $(this);
                let colIndex = obj.parents('th').index();
                $(".st-tr:visible",obj.parents('.st-table')).each(function(){
                    $('td:eq('+colIndex+') :checkbox',this).prop("checked", obj.prop("checked") ? true:false);
                });
            });

            //添加点击选中行变色的功能，通过focusRowColor属性控制，可以true、false 或颜色值
            if(options.focusRowMode != undefined  && options.focusRowMode != ""){
                let focusRowMode = options.focusRowMode;
                let focusRowColor = options.focusRowColor;
                tableJqo.on('click',".st-td", function(){ //绑定tr不起作用
                    // event.stopPropagation(); event.preventDefault();
                    let color = focusRowColor != undefined && focusRowColor != "" ? focusRowColor : "aliceblue";
                    // $(".st-td",$(this).parents("table")).css({"background-color": ""});
                    // $(this).parents(".st-tr").find(".st-td").css({"background-color": color});
                    let stTrJqo =  $(this).parents(".st-tr");
                    if(focusRowMode == "radio"){
                        $(".st-tr",$(this).parents("table")).css({"background-color": ""}).attr("focusrow","false");
                        stTrJqo.css({"background-color": color}).attr("focusrow","true");
                    }else if(focusRowMode == "check"){
                        stTrJqo.attr("focusrow") == "true" ? stTrJqo.css({"background-color": ""}).attr("focusrow","false")
                            : stTrJqo.css({"background-color": color}).attr("focusrow","true")
                    }else{
                        alert("参数错误");
                    }
                })
            }

        },

        stAddRow:function(datas , direct , target){
            let tr, td, column ,tdSpan  , rowData , options = $(this).data("options");
            let columns = options.columns;
            if($.isArray(datas)){
                for(let i=0;i<datas.length;i++){

                    tr = $("<tr class='st-tr'/></tr>");

                    if(direct == undefined) direct = "last";

                    if(direct == "first"){
                        tr.prependTo( $(this).find("tbody") );
                    }else if(direct == "last"){
                        tr.appendTo( $(this).find("tbody") );
                    }else if(direct == "up"){
                        $(target).parents(".st-tr").before(tr)
                    }else if(direct == "down"){
                        $(target).parents(".st-tr").after(tr)
                    }else{
                        alert("参数错误");
                        return ;
                    }

                    if(options.paging == true && options.pageMode == "local"){ //本地分页模式下先隐藏，由分页函数控制显示
                        tr.hide();
                    }

                    rowData = datas[i] ;
                    tr.data("data",rowData);
                    for(var j=0;j<columns.length;j++){
                        column = columns[j];
                        td = $("<td class='st-td'></td>").appendTo(tr); //不支持拖拽换列，否则对不上。

                        if(column.style != undefined) td.attr("style",column.style);
                        if(column.align != undefined ) td.addClass("text-"+column.align); //默认靠左

                        if(column.render != undefined){
                            let content = column.render( rowData[column.data] , rowData , td , tr , this);
                            // if(/<[^>]*>/.test(content)) td.css("padding",0); //由column 的style控制，这里不做多余的
                            td.html(content);
                        }else{
                            td.text(rowData[column.data]);
                        }

                        if(column.left != undefined){
                            td.css({"left": column.left + "px"});
                            td.addClass("st-fixed-left");
                            if(options.fixedLeft == j+1) td.addClass("st-fixed-left-last");
                        }
                        if(column.right != undefined){
                            td.css({"right": column.right + "px"});
                            td.addClass("st-fixed-right");
                            if(options.fixedRight == options.columns.length - j) td.addClass("st-fixed-right-first");
                        }

                        if(column.afterRender != undefined ){
                            column.afterRender(rowData[column.data] , rowData , td);
                        }
                    }
                }

                if(options.afterRowRender != undefined ){
                    options.afterRowRender(rowData , tr);
                }
            }else{
                tr = $("<tr/>");
                if(target != undefined){ //中间添加行使用
                    if(direct == "up"){
                        $(target).parents(".st-tr").before(tr);
                    }else{
                        $(target).parents(".st-tr").after(tr)
                    }
                    tr.addClass("st-tr");
                }else{
                    tr.appendTo( $(this).find("tbody") ).addClass("st-tr");
                }
                $(datas).appendTo(tr);

                if(options.afterRowRender != undefined ){
                    options.afterRowRender(null , tr);
                }
            }
        },

        stDelRow:function(obj){
            let trInner = $(obj);
            if(trInner.hasClass(".st-tr")){
                trInner.remove();
            }else{
                trInner.parents(".st-tr").remove();
            }
        },

        stGetRowData:function(target){
            if(Number.isInteger(target)){
                return $(".st-tr",this).eq(target).data("data");
            }else{
                let trInner = $(target);
                if(trInner.hasClass(".st-tr")){
                    return trInner.data("data");
                }else{
                    return trInner.parents(".st-tr").data("data");
                }
            }
        },

        stGetRowCount:function(){
            return $(".st-tr",this).length;
        },

        stGetFocusRow:function(){
            let focusRowMode = $(this).data("options").focusRowMode;
            if(focusRowMode == "radio"){
                return $(".st-tr[focusrow=true]",this).eq(0).index();
            }else if(focusRowMode == "check"){
                let res = [];
                let focusRowJqos =  $(".st-tr[focusrow=true]",this);
                for(let i=0;i<focusRowJqos.length;i++){
                    res.push(focusRowJqos.eq(i).index());
                }
                return res;
            }else{
                return undefined;
            }
        },

        stRefreshData:function( datas , totalPage , pageNum){
            $(this).find("tbody").html("");
            $(this).stAddRow(datas);

            if($(this).data("options").group != undefined && $(this).data("options").group != ""){
                _group(this,0 , $(this).data("options").group.split(">") ,  datas, 0 );
            }
            _initPaginate(this , totalPage , pageNum);
        },

    })
})(jQuery)